#ifndef __FORMAT_HPP___
#define __FORMAT_HPP___

#include <iostream>
#include <sstream>
#include <ctime>
#include <cassert>
#include <string>
#include <memory>
#include <vector>
#include "Message.hpp"
#include "Level.hpp"
#include "Until.hpp"

namespace Logs
{
    class FormatItem
    {
    public:
        using Ptr = std::shared_ptr<FormatItem>;
        virtual ~FormatItem() {};
        virtual void FomatPrint(std::ostream& out,const Message& msg) = 0;
    };
    class MessageFormatItem : public FormatItem
    {
    public:
        void FomatPrint(std::ostream& out,const Message& msg) override
        {
            out << msg._message;
        }
    };
    class LevelFormatItem : public FormatItem
    {
    public:
        void FomatPrint(std::ostream& out,const Message& msg) override
        {
            Level l;
            out << l.To_String(msg._level);
        }
    };
    class TimeFormatItem : public FormatItem
    {
    public:
        TimeFormatItem(std::string format = "%H:%M:%S")
            :_format(format)
        {}
        void FomatPrint(std::ostream& out,const Message& msg) override
        {
            struct tm t;
            //struct tm* ctime = localtime_r(&(msg._ctime),&t);
            time_t now = Until::Time::GetTime();
            struct tm* ctime = localtime_r(&(now),&t);
            char buffer[50];
            strftime(buffer,sizeof(buffer),_format.c_str(),ctime);
            out << buffer;
        }
    private:
        std::string _format;
    };
    class FileFormatItem : public FormatItem
    {
    public:
        void FomatPrint(std::ostream& out,const Message& msg) override
        {
            out << msg._file;
        }
    };
    class LineFormatItem : public FormatItem
    {
    public:
        void FomatPrint(std::ostream& out,const Message& msg) override
        {
            out << msg._line;
        }
    };
    class LoggerFormatItem : public FormatItem
    {
    public:
        void FomatPrint(std::ostream& out,const Message& msg) override
        {
            out << msg._logger;
        }
    };
    class TidFormatItem : public FormatItem
    {
    public:
        void FomatPrint(std::ostream& out,const Message& msg) override
        {
            out << msg._tid;
        }
    };
    class TABFormatItem : public FormatItem
    {
    public:
        void FomatPrint(std::ostream& out,const Message& msg) override
        {
            out << "\t";
        }
    };
    class NewLineFormatItem : public FormatItem
    {
    public:
        void FomatPrint(std::ostream& out,const Message& msg) override
        {
            out << "\n";
        }
    };
    class OtherFormatItem : public FormatItem
    {
    public:
        OtherFormatItem(const std::string& str)
            :_str(str)
        {
            ;
        }
        void FomatPrint(std::ostream& out,const Message& msg) override
        {
            out << _str;
        }
    private: 
        std::string _str;
    };
    class Formatter
    {
    public:
        using Ptr = std::shared_ptr<Formatter>;
        Formatter(const std::string& pattern = "[%d{%H:%M:%S}[%t][%c][%f:%l][%p]%T%m%n]")
            :_pattern(pattern)
        {
            // 必须解析成功，不然就不知道以何种形式返回。
            // 不然就终止。
            assert(parsePattern());
        }
        // 对msg进行格式化。
        void format(std::ostream& out,const Message& msg)
        {
            for(auto item : _items)
            {
                item->FomatPrint(out,msg);
            }
        }
        std::string format(const Message& msg)
        {
            std::stringstream ss;
            ss << msg._ctime
            << Level::To_String(msg._level)
            << msg._file
            << msg._line
            << msg._message
            << msg._logger;

            return ss.str();
        }
        // 对格式化规则字符串进行解析。
        bool parsePattern()
        {
            std::string key, val ;
            std::vector<std::pair<std::string , std::string>> fmt_order;

            size_t pos = 0;

            while(pos < _pattern.size())
            {
                // 非格式串字符。
                if(_pattern[pos] != '%')
                {
                    val.push_back(_pattern[pos]);
                    ++pos;
                    continue;
                }
                // 就是普通的%%转义字符。
                if(pos + 1 < _pattern.size() && _pattern[pos] != '%')
                {
                    val.push_back(_pattern[pos]);
                    pos += 2;
                    continue;
                }
                // 接下来就一定是固定格式字符串。
                ++pos;
                if(pos >= _pattern.size())
                {
                    std::cout << "%%格式错误" << std::endl;
                    return false;
                }
                key.push_back(_pattern[pos]);
                ++pos;
                // 没有值，可以不插入，避免浪费时间空间。
                if(val.empty() == false)
                {
                    fmt_order.push_back(std::make_pair("",val));
                    val.clear();
                }
                if(pos + 1 == _pattern.size() && _pattern[pos] == '{')
                {
                    std::cout << "子格式串错误" << std::endl;
                    return false;
                }
                // 紧随格式化字符之后，有没有'{'，如果有，则'}'之后，之前的数据是格式化字符的子格式。
                if(pos < _pattern.size() && _pattern[pos] == '{')
                {
                    ++pos;
                    // 如果没有'}'说明这个格式有问题。
                    while(pos < _pattern.size() && _pattern[pos] != '}')
                    {
                        // 就是无需变化的格式串。
                        val.push_back(_pattern[pos]);
                        ++pos;
                    }
                    if(pos == _pattern.size())
                    {
                        std::cout << "子格式错误" << std::endl;
                        return false;
                    }
                }
                // 怕还有其他的key、val没有保存。
                fmt_order.push_back(std::make_pair(key,val));
                key.clear();
                val.clear();
            }

            // 保存所有格式。
            for(auto& it : fmt_order)
            {
                _items.push_back(createItem(it.first,it.second));
            }

            return true;
        }
        // 根据不同的格式化字符串创建不同的个数话子项对象。
        FormatItem::Ptr createItem(const std::string& key,const std::string& val)
        {
            if(key == "d") return std::make_shared<TimeFormatItem>(val);
            if(key == "t") return std::make_shared<TidFormatItem>();
            if(key == "c") return std::make_shared<LoggerFormatItem>();
            if(key == "f") return std::make_shared<FileFormatItem>();
            if(key == "l") return std::make_shared<LineFormatItem>();
            if(key == "p") return std::make_shared<LevelFormatItem>();
            if(key == "T") return std::make_shared<TABFormatItem>();
            if(key == "m") return std::make_shared<MessageFormatItem>();
            if(key == "n") return std::make_shared<NewLineFormatItem>();

            return std::make_shared<OtherFormatItem>(val);
        }
    private:
        std::string _pattern;
        std::vector<FormatItem::Ptr> _items;
    };
}

#endif